home *** CD-ROM | disk | FTP | other *** search
/ AMIGA-CD 2 / Amiga-CD - Volume 2.iso / gepackte_disketten / 1994 / 08_94_5.dms / 08_94_5.adf / term-4.0-Source.lha / termPhone.c < prev    next >
C/C++ Source or Header  |  1994-06-16  |  17KB  |  745 lines

  1. /*
  2. **    termPhone.c
  3. **
  4. **    Phonebook support routines
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* RemoveDialEntry(LONG Entry):
  13.      *
  14.      *    Remove a phone book entry from the dial list.
  15.      */
  16.  
  17. VOID __regargs
  18. RemoveDialEntry(LONG Entry)
  19. {
  20.     LONG Count = Phonebook[Entry] -> Count,i;
  21.  
  22.     for(i = 0 ; i < NumPhoneEntries ; i++)
  23.     {
  24.         if(Phonebook[i] -> Count > Count)
  25.             SPrintf(Phonebook[i] -> Node -> LocalName,"%3ld - %s",Phonebook[i] -> Count--,Phonebook[i] -> Header -> Name);
  26.     }
  27.  
  28.     Phonebook[Entry] -> Count = -1;
  29.  
  30.     SPrintf(Phonebook[Entry] -> Node -> LocalName,"      %s",Phonebook[Entry] -> Header -> Name);
  31. }
  32.  
  33.     /* RemoveDialNode(struct PhoneNode *Node):
  34.      *
  35.      *    Remove a node from the dialing list.
  36.      */
  37.  
  38. VOID __regargs
  39. RemoveDialNode(struct PhoneNode *Node)
  40. {
  41.         /* If it's got a name it was built in the phone book panel,
  42.          * else the ARexx interface has linked it into the list.
  43.          */
  44.  
  45.     if(Node -> VanillaNode . ln_Name[0])
  46.     {
  47.         LONG Count = Node -> Entry -> Count,i;
  48.  
  49.             /* Adjust all entries. */
  50.  
  51.         for(i = 0 ; i < NumPhoneEntries ; i++)
  52.         {
  53.             if(Phonebook[i] -> Count > Count)
  54.                 Phonebook[i] -> Count--;
  55.         }
  56.  
  57.             /* Can the index count. */
  58.  
  59.         Node -> Entry -> Count = -1;
  60.     }
  61. }
  62.  
  63.     /* SortToList(struct PhoneNode *PhoneNode):
  64.      *
  65.      *    Add a node to the dial list.
  66.      */
  67.  
  68. VOID __regargs
  69. SortToList(struct PhoneNode *PhoneNode)
  70. {
  71.         /* No dial list prepared? Let's create one! */
  72.  
  73.     if(!DialList)
  74.     {
  75.         if(DialList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  76.             NewList(DialList);
  77.     }
  78.  
  79.         /* Do we have a dial list to mangle? */
  80.  
  81.     if(DialList)
  82.     {
  83.         struct PhoneNode *NewNode;
  84.  
  85.             /* Create a new node to be added to the dial list. */
  86.  
  87.         if(NewNode = (struct PhoneNode *)AllocVecPooled(sizeof(struct PhoneNode),MEMF_ANY | MEMF_CLEAR))
  88.         {
  89.             struct PhoneNode *Node = (struct PhoneNode *)DialList -> lh_Head;
  90.  
  91.                 /* Take care of the name and the corresponding phone book entry. */
  92.  
  93.             NewNode -> VanillaNode . ln_Name    = NewNode -> LocalName;
  94.             NewNode -> Entry            = PhoneNode -> Entry;
  95.  
  96.             strcpy(NewNode -> LocalName,PhoneNode -> LocalName);
  97.  
  98.                 /* Install back-link. */
  99.  
  100.             NewNode -> Entry -> Node = NewNode;
  101.  
  102.                 /* Sort the node into the list. */
  103.  
  104.             while(Node -> VanillaNode . ln_Succ)
  105.             {
  106.                 if(Node -> Entry -> Count > NewNode -> Entry -> Count)
  107.                 {
  108.                     if(Node == (struct PhoneNode *)DialList -> lh_Head)
  109.                         AddHead(DialList,&NewNode -> VanillaNode);
  110.                     else
  111.                         Insert(DialList,&NewNode -> VanillaNode,Node -> VanillaNode . ln_Pred);
  112.  
  113.                     return;
  114.                 }
  115.  
  116.                 Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ;
  117.             }
  118.  
  119.             AddTail(DialList,&NewNode -> VanillaNode);
  120.         }
  121.     }
  122. }
  123.  
  124.     /* FreeDialList(BYTE ClearAll):
  125.      *
  126.      *    Release the contents of the dial list.
  127.      */
  128.  
  129. VOID __regargs
  130. FreeDialList(BYTE ClearAll)
  131. {
  132.     if(DialList)
  133.     {
  134.         struct PhoneNode *SubNode = (struct PhoneNode *)DialList -> lh_Head,*NextNode;
  135.  
  136.         while(NextNode = (struct PhoneNode *)SubNode -> VanillaNode . ln_Succ)
  137.         {
  138.             if(ClearAll || !SubNode -> VanillaNode . ln_Name[0])
  139.                 FreeVecPooled(SubNode);
  140.  
  141.             SubNode = NextNode;
  142.         }
  143.  
  144.         FreeVecPooled(DialList);
  145.  
  146.         DialList = NULL;
  147.     }
  148. }
  149.  
  150.     /* CreatePhoneList():
  151.      *
  152.      *    Turn the array of pointers to phonebook entries into
  153.      *    a linked standard Amiga List (gadtools needs this).
  154.      */
  155.  
  156. struct List *
  157. CreatePhoneList()
  158. {
  159.     struct List *PhoneList;
  160.  
  161.     if(Phonebook && NumPhoneEntries)
  162.     {
  163.         struct PhoneNode *PhoneNode;
  164.  
  165.         if(PhoneList = (struct List *)AllocVecPooled(sizeof(struct List) + NumPhoneEntries * sizeof(struct PhoneNode),MEMF_ANY | MEMF_CLEAR))
  166.         {
  167.             LONG i;
  168.  
  169.             NewList(PhoneList);
  170.  
  171.             PhoneNode = (struct PhoneNode *)(PhoneList + 1);
  172.  
  173.             for(i = 0 ; i < NumPhoneEntries ; i++)
  174.             {
  175.                 if(Phonebook[i] -> Count != -1)
  176.                     SPrintf(PhoneNode[i] . LocalName,"%3ld - %s",Phonebook[i] -> Count + 1,Phonebook[i] -> Header -> Name);
  177.                 else
  178.                     SPrintf(PhoneNode[i] . LocalName,"      %s",Phonebook[i] -> Header -> Name);
  179.  
  180.                 PhoneNode[i] . VanillaNode . ln_Name = PhoneNode[i] . LocalName;
  181.  
  182.                 Phonebook[i] -> Node = &PhoneNode[i];
  183.  
  184.                 PhoneNode[i] . Entry = Phonebook[i];
  185.  
  186.                 AddTail(PhoneList,&PhoneNode[i]);
  187.             }
  188.  
  189.             return(PhoneList);
  190.         }
  191.     }
  192.     else
  193.     {
  194.         if(PhoneList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  195.         {
  196.             NewList(PhoneList);
  197.  
  198.             return(PhoneList);
  199.         }
  200.     }
  201.  
  202.     return(NULL);
  203. }
  204.  
  205.     /* DeletePhoneList(struct List *PhoneList):
  206.      *
  207.      *    Delete the entries listed in the Amiga List
  208.      *    created by the routine above.
  209.      */
  210.  
  211. VOID __regargs
  212. DeletePhoneList(struct List *PhoneList)
  213. {
  214.     if(PhoneList)
  215.         FreeVecPooled(PhoneList);
  216. }
  217.  
  218.     /* Compare(struct PhoneEntry **A,struct PhoneEntry **B):
  219.      *
  220.      *    Comparison subroutine required by the QuickSort
  221.      *    call below.
  222.      */
  223.  
  224. STATIC int __stdargs
  225. Compare(struct PhoneEntry **A,struct PhoneEntry **B)
  226. {
  227.         /* Has entry A been selected? */
  228.  
  229.     if((*A) -> Count == -1)
  230.     {
  231.             /* If entry B isn't selected either, compare the
  232.              * names lexically, else entry B is supposed
  233.              * to be `smaller' than entry A.
  234.              */
  235.  
  236.         if((*B) -> Count == -1)
  237.             return(Stricmp((*A) -> Header -> Name,(*B) -> Header -> Name));
  238.         else
  239.             return(1);
  240.     }
  241.     else
  242.     {
  243.             /* If entry B isn't selected, entry A is supposed
  244.              * to be `smaller' than entry B, else return
  245.              * the difference between both entries.
  246.              */
  247.  
  248.         if((*B) -> Count == -1)
  249.             return(-1);
  250.         else
  251.             return((*A) -> Count - (*B) -> Count);
  252.     }
  253. }
  254.  
  255.     /* SortPhoneEntries():
  256.      *
  257.      *    Sorts the current phone list array in ascending order.
  258.      */
  259.  
  260. VOID
  261. SortPhoneEntries()
  262. {
  263.     qsort((APTR)Phonebook,NumPhoneEntries,sizeof(struct PhoneEntry *),Compare);
  264. }
  265.  
  266.     /* FreeTimeDateNode(struct TimeDateNode *Node):
  267.      *
  268.      *    Free the memory allocated for a TimeDateNode and
  269.      *    the associated data table.
  270.      */
  271.  
  272. VOID __regargs
  273. FreeTimeDateNode(struct TimeDateNode *Node)
  274. {
  275.     FreeVecPooled(Node -> Table);
  276.  
  277.     FreeVecPooled(Node);
  278. }
  279.  
  280.     /* FreeTimeDateList(struct List *List):
  281.      *
  282.      *    Free a list of TimeDateNodes.
  283.      */
  284.  
  285. VOID __regargs
  286. FreeTimeDateList(struct List *List)
  287. {
  288.     struct Node *Node = List -> lh_Head,*NextNode;
  289.  
  290.     while(NextNode = Node -> ln_Succ)
  291.     {
  292.         Remove(Node);
  293.  
  294.         FreeTimeDateNode((struct TimeDateNode *)Node);
  295.  
  296.         Node = NextNode;
  297.     }
  298. }
  299.  
  300.     /* CopyTimeDateList(struct List *From,struct List *To,BYTE SkipFirst):
  301.      *
  302.      *    Copies the TimeDateNode list from one location into
  303.      *    another.
  304.      */
  305.  
  306. VOID __regargs
  307. CopyTimeDateList(struct List *From,struct List *To,BYTE SkipFirst)
  308. {
  309.     struct TimeDateNode *FromNode,*ToNode;
  310.  
  311.     FromNode = (struct TimeDateNode *)From -> lh_Head;
  312.  
  313.     if(SkipFirst)
  314.         FromNode = (struct TimeDateNode *)FromNode -> VanillaNode . ln_Succ;
  315.  
  316.     while(FromNode -> VanillaNode . ln_Succ)
  317.     {
  318.         if(ToNode = (struct TimeDateNode *)AllocVecPooled(sizeof(struct TimeDateNode),MEMF_ANY))
  319.         {
  320.             CopyMem(FromNode,ToNode,sizeof(struct TimeDateNode));
  321.  
  322.             ToNode -> VanillaNode . ln_Name = ToNode -> Buffer;
  323.  
  324.             if(ToNode -> Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * FromNode -> Table[0] . Count,MEMF_ANY))
  325.             {
  326.                 CopyMem(FromNode -> Table,ToNode -> Table,sizeof(struct TimeDate) * FromNode -> Table[0] . Count);
  327.  
  328.                 AddTail(To,&ToNode -> VanillaNode);
  329.             }
  330.             else
  331.                 FreeVecPooled(ToNode);
  332.         }
  333.  
  334.         FromNode = (struct TimeDateNode *)FromNode -> VanillaNode . ln_Succ;
  335.     }
  336. }
  337.  
  338.     /* AdaptTimeDateNode(struct TimeDateNode *Node):
  339.      *
  340.      *    Adapt the title and comment of a TimeDateNode.
  341.      */
  342.  
  343. VOID __regargs
  344. AdaptTimeDateNode(struct TimeDateNode *Node)
  345. {
  346.     STRPTR Comment = Node -> Header . Comment[0] ? Node -> Header . Comment : LocaleString(MSG_TERMPHONE_NO_COMMENT_TXT);
  347.  
  348.     if(Node -> Header . Month == -1)
  349.     {
  350.         if(Node -> Header . Day == -1)
  351.             strcpy(Node -> Buffer,LocaleString(MSG_TERMPHONE_STANDARD_SETTINGS_TXT));
  352.         else
  353.             SPrintf(Node -> Buffer,LocaleString(MSG_TERMPHONE_DAYS_TXT),Comment);
  354.     }
  355.     else
  356.         SPrintf(Node -> Buffer,"%2ld %s » %s",Node -> Header . Day,LocaleString(MSG_TERMPHONE_JAN_TXT + Node -> Header . Month),Comment);
  357. }
  358.  
  359.     /* TimeCompare(struct TimeDate *A,struct TimeDate *B):
  360.      *
  361.      *    Comparison routine required by SortTimeTable().
  362.      */
  363.  
  364. STATIC int __stdargs
  365. TimeCompare(struct TimeDate *A,struct TimeDate *B)
  366. {
  367.     return(((LONG)A -> Time) - ((LONG)B -> Time));
  368. }
  369.  
  370.     /* SortTimeTable(struct TimeDateNode *Node):
  371.      *
  372.      *    Sort the time table associated with a
  373.      *    TimeDateNode in ascending order.
  374.      */
  375.  
  376. VOID __regargs
  377. SortTimeTable(struct TimeDateNode *Node)
  378. {
  379.     qsort((APTR)Node -> Table,Node -> Table[0] . Count,sizeof(struct TimeDate),TimeCompare);
  380. }
  381.  
  382.     /* BuildTimeList(struct TimeDateNode *Node):
  383.      *
  384.      *    Build a read-to-display time table list from a TimeDateNode.
  385.      */
  386.  
  387. struct List * __regargs
  388. BuildTimeList(struct TimeDateNode *Node)
  389. {
  390.     struct List *List;
  391.  
  392.     if(List = (struct List *)AllocVecPooled(sizeof(struct List) + Node -> Table[0] . Count * sizeof(struct TimeNode),MEMF_ANY | MEMF_CLEAR))
  393.     {
  394.         struct TimeNode    *Time = (struct TimeNode *)(List + 1);
  395.         UBYTE         LocalBuffer[40];
  396.         LONG         i;
  397.  
  398.         NewList(List);
  399.  
  400.         for(i = 0 ; i < Node -> Table[0] . Count ; i++)
  401.         {
  402.             Time[i] . VanillaNode . ln_Name    = Time[i] . Name;
  403.             Time[i] . Time            = Node -> Table[i] . Time;
  404.  
  405.             FormatTime(LocalBuffer,Time[i] . Time / 6,(Time[i] . Time % 6) * 10,-1);
  406.  
  407.             LocalBuffer[19] = 0;
  408.  
  409.             strcpy(Time[i] . Name,LocalBuffer);
  410.  
  411.             AddTail(List,&Time[i]);
  412.         }
  413.     }
  414.  
  415.     return(List);
  416. }
  417.  
  418.     /* ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time):
  419.      *
  420.      *    Resize the time table associated with a TimeDateNode.
  421.      */
  422.  
  423. BYTE __regargs
  424. ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time)
  425. {
  426.     if(Count != Node -> Table[0] . Count)
  427.     {
  428.         struct TimeDate *Table;
  429.  
  430.         if(Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  431.         {
  432.             LONG i;
  433.  
  434.             CopyMem(Node -> Table,Table,sizeof(struct TimeDate) * Count);
  435.  
  436.             if(Count > Node -> Table[0] . Count)
  437.             {
  438.                 for(i = Node -> Table[0] . Count ; i < Count ; i++)
  439.                 {
  440.                     CopyMem(&Node -> Table[0],&Table[i],sizeof(struct TimeDate));
  441.  
  442.                     Table[i] . Time = Time;
  443.                 }
  444.             }
  445.  
  446.             for(i = 0 ; i < Count ; i++)
  447.                 Table[i] . Count = Count;
  448.  
  449.             FreeVecPooled(Node -> Table);
  450.  
  451.             Node -> Table = Table;
  452.  
  453.             return(TRUE);
  454.         }
  455.         else
  456.             return(FALSE);
  457.     }
  458.     else
  459.         return(TRUE);
  460. }
  461.  
  462.     /* DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index):
  463.      *
  464.      *    Delete a single timetable entry from a TimeDateNode.
  465.      */
  466.  
  467. BYTE __regargs
  468. DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index)
  469. {
  470.     struct TimeDate    *Table;
  471.     LONG         Count = Node -> Table[0] . Count - 1;
  472.  
  473.     if(Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  474.     {
  475.         LONG i,j;
  476.  
  477.         for(i = j = 0 ; i < Node -> Table[0] . Count ; i++)
  478.         {
  479.             if(i != Index)
  480.             {
  481.                 CopyMem(&Node -> Table[i],&Table[j],sizeof(struct TimeDate));
  482.  
  483.                 Table[j++] . Count = Count;
  484.             }
  485.         }
  486.  
  487.         FreeVecPooled(Node -> Table);
  488.  
  489.         Node -> Table = Table;
  490.  
  491.         return(TRUE);
  492.     }
  493.     else
  494.         return(FALSE);
  495. }
  496.  
  497.     /* CreateTimeDateNode(BYTE Month,BYTE Day,STRPTR Comment,LONG Count):
  498.      *
  499.      *    Create a new TimeDateNode including time table entries.
  500.      */
  501.  
  502. struct TimeDateNode * __regargs
  503. CreateTimeDateNode(BYTE Month,BYTE Day,STRPTR Comment,LONG Count)
  504. {
  505.     struct TimeDateNode *Node;
  506.  
  507.     if(Node = (struct TimeDateNode *)AllocVecPooled(sizeof(struct TimeDateNode),MEMF_ANY | MEMF_CLEAR))
  508.     {
  509.         if(Node -> Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  510.         {
  511.             Node -> VanillaNode . ln_Name            = Node -> Buffer;
  512.  
  513.             Node -> Header . Month                = Month;
  514.             Node -> Header . Day                = Day;
  515.  
  516.             Node -> Table[0] . PayPerUnit[DT_FIRST_UNIT]    = 23;
  517.             Node -> Table[0] . SecPerUnit[DT_FIRST_UNIT]    =  6 * 60;
  518.             Node -> Table[0] . PayPerUnit[DT_NEXT_UNIT]    = 23;
  519.             Node -> Table[0] . SecPerUnit[DT_NEXT_UNIT]    =  6 * 60;
  520.             Node -> Table[0] . Time                = DT_GET_TIME( 8,0);
  521.             Node -> Table[0] . Count            = Count;
  522.  
  523.             if(Count > 1)
  524.             {
  525.                 Node -> Table[1] . PayPerUnit[DT_FIRST_UNIT]    = 23;
  526.                 Node -> Table[1] . SecPerUnit[DT_FIRST_UNIT]    = 12 * 60;
  527.                 Node -> Table[1] . PayPerUnit[DT_NEXT_UNIT]    = 23;
  528.                 Node -> Table[1] . SecPerUnit[DT_NEXT_UNIT]    = 12 * 60;
  529.                 Node -> Table[1] . Time                = DT_GET_TIME(18,0);
  530.                 Node -> Table[1] . Count            = Count;
  531.             }
  532.  
  533.             strcpy(Node -> Header . Comment,Comment);
  534.  
  535.             AdaptTimeDateNode(Node);
  536.  
  537.             return(Node);
  538.         }
  539.         else
  540.             FreeVecPooled(Node);
  541.     }
  542.  
  543.     return(NULL);
  544. }
  545.  
  546.     /* RemPhoneEntry(LONG Num):
  547.      *
  548.      *    Remove a given entry from the phone book.
  549.      */
  550.  
  551. VOID __regargs
  552. RemPhoneEntry(LONG Num)
  553. {
  554.     struct PhoneEntry    *Entry;
  555.     LONG             i;
  556.  
  557.     Entry = Phonebook[Num];
  558.  
  559.     for(i = Num ; i < NumPhoneEntries ; i++)
  560.         Phonebook[i] = Phonebook[i + 1];
  561.  
  562.     Phonebook[NumPhoneEntries--] = NULL;
  563.  
  564.     if(Entry -> Config)
  565.         DeleteConfiguration(Entry -> Config);
  566.  
  567.     FreeTimeDateList((struct List *)&Entry -> TimeDateList);
  568.  
  569.     FreeVecPooled(Entry);
  570. }
  571.  
  572.     /* NewPhoneEntry():
  573.      *
  574.      *    Create a new phone book entry with default values and
  575.      *    add it to the array. Expand the phone book if necessary.
  576.      */
  577.  
  578. BYTE
  579. NewPhoneEntry()
  580. {
  581.     struct PhoneEntry    **PrivatePhonebook;
  582.     LONG             PrivatePhoneSize,i;
  583.  
  584.         /* The phone book is filled `to the brim', so let's expand
  585.          * it.
  586.          */
  587.  
  588.     if(NumPhoneEntries + 1 > PhoneSize)
  589.     {
  590.             /* Allocate another phone book. */
  591.  
  592.         if(PrivatePhonebook = CreatePhonebook(PhoneSize + 1,&PrivatePhoneSize,FALSE))
  593.         {
  594.                 /* Copy the data. */
  595.  
  596.             if(Phonebook && PhoneSize)
  597.             {
  598.                 for(i = 0 ; i < PhoneSize ; i++)
  599.                     PrivatePhonebook[i] = Phonebook[i];
  600.  
  601.                     /* Remove the old phonebook. */
  602.  
  603.                 DeletePhonebook(Phonebook,PhoneSize,FALSE);
  604.             }
  605.  
  606.                 /* Assign the new pointers. */
  607.  
  608.             Phonebook = PrivatePhonebook;
  609.             PhoneSize = PrivatePhoneSize;
  610.         }
  611.         else
  612.             return(FALSE);
  613.     }
  614.  
  615.         /* Allocate another entry and add it to the phone book. */
  616.  
  617.     if(Phonebook[NumPhoneEntries] = (struct PhoneEntry *)AllocVecPooled(sizeof(struct PhoneEntry) + sizeof(struct PhoneHeader),MEMF_ANY | MEMF_CLEAR))
  618.     {
  619.         if(Phonebook[NumPhoneEntries] -> Config = CreateConfiguration(FALSE))
  620.         {
  621.             struct TimeDateNode *TimeDateNode;
  622.  
  623.             Phonebook[NumPhoneEntries] -> Header = (struct PhoneHeader *)(Phonebook[NumPhoneEntries] + 1);
  624.  
  625.             strcpy(Phonebook[NumPhoneEntries] -> Header -> Name,LocaleString(MSG_TERMPHONE_UNUSED_ENTRY_TXT));
  626.  
  627.             Phonebook[NumPhoneEntries] -> Count = -1;
  628.  
  629.             NewList((struct List *)&Phonebook[NumPhoneEntries] -> TimeDateList);
  630.  
  631.             if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
  632.                 AddTail((struct List *)&Phonebook[NumPhoneEntries] -> TimeDateList,&TimeDateNode -> VanillaNode);
  633.  
  634.             NumPhoneEntries++;
  635.  
  636.             return(TRUE);
  637.         }
  638.  
  639.         FreeVecPooled(Phonebook[NumPhoneEntries]);
  640.  
  641.         Phonebook[NumPhoneEntries] = NULL;
  642.     }
  643.  
  644.     return(FALSE);
  645. }
  646.  
  647.     /* CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries):
  648.      *
  649.      *    Create a new phone entry array (so-called phone book).
  650.      */
  651.  
  652. struct PhoneEntry ** __regargs
  653. CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries)
  654. {
  655.     struct PhoneEntry **PhoneEntry = NULL;
  656.  
  657.     if(Size)
  658.     {
  659.             /* Round the number of phone entries to a
  660.              * multiple of eight.
  661.              */
  662.  
  663.         *AllocSize = (Size + 7) & ~7;
  664.  
  665.             /* Create the list of pointers. */
  666.  
  667.         if(PhoneEntry = (struct PhoneEntry **)AllocVecPooled(*AllocSize * sizeof(struct PhoneEntry *),MEMF_ANY | MEMF_CLEAR))
  668.         {
  669.                 /* And create some entries if necessary. */
  670.  
  671.             if(CreateEntries)
  672.             {
  673.                 BYTE Success = TRUE;
  674.                 LONG i;
  675.  
  676.                 for(i = 0 ; Success && i < Size ; i++)
  677.                 {
  678.                     if(PhoneEntry[i] = (struct PhoneEntry *)AllocVecPooled(sizeof(struct PhoneEntry) + sizeof(struct PhoneHeader),MEMF_ANY | MEMF_CLEAR))
  679.                     {
  680.                         if(PhoneEntry[i] -> Config = CreateConfiguration(FALSE))
  681.                         {
  682.                             PhoneEntry[i] -> Header = (struct PhoneHeader *)(PhoneEntry[i] + 1);
  683.  
  684.                             NewList((struct List *)&PhoneEntry[i] -> TimeDateList);
  685.                         }
  686.                         else
  687.                             Success = FALSE;
  688.                     }
  689.                     else
  690.                         Success = FALSE;
  691.                 }
  692.  
  693.                 if(!Success)
  694.                 {
  695.                     for(i = 0 ; i < *AllocSize ; i++)
  696.                     {
  697.                         if(PhoneEntry[i])
  698.                         {
  699.                             if(PhoneEntry[i] -> Config)
  700.                                 DeleteConfiguration(PhoneEntry[i] -> Config);
  701.  
  702.                             FreeVecPooled(PhoneEntry[i]);
  703.                         }
  704.                     }
  705.  
  706.                     FreeVecPooled(PhoneEntry);
  707.  
  708.                     return(NULL);
  709.                 }
  710.             }
  711.         }
  712.     }
  713.  
  714.     return(PhoneEntry);
  715. }
  716.  
  717.     /* DeletePhonebook(struct PhoneEntry **PhoneBook,LONG Size,BYTE FreeEntries):
  718.      *
  719.      *    Deallocates a given phone book and its entries if necessary.
  720.      */
  721.  
  722. VOID __regargs
  723. DeletePhonebook(struct PhoneEntry **Phonebook,LONG Size,BYTE FreeEntries)
  724. {
  725.     if(FreeEntries)
  726.     {
  727.         LONG i;
  728.  
  729.         for(i = 0 ; i < Size ; i++)
  730.         {
  731.             if(Phonebook[i])
  732.             {
  733.                 FreeTimeDateList((struct List *)&Phonebook[i] -> TimeDateList);
  734.  
  735.                 if(Phonebook[i] -> Config)
  736.                     DeleteConfiguration(Phonebook[i] -> Config);
  737.  
  738.                 FreeVecPooled(Phonebook[i]);
  739.             }
  740.         }
  741.     }
  742.  
  743.     FreeVecPooled(Phonebook);
  744. }
  745.